const util = require("./util")
const underscore = require('./underscore.js')

const bluetooth = {
  last_cap : [],
  busy : false,
  deviceName : "",
  serviceId : '0000FFF0-0000-1000-8000-00805F9B34FB',
  writeCharacteristicId: '0000FFF2-0000-1000-8000-00805F9B34FB',
  notifyCharacteristicId : '0000FFF1-0000-1000-8000-00805F9B34FB',
  deviceId : '',
  devices : [],
  last_available : false,
  available : false, // 设备可用
  discovering : false, // 搜索状态
  bFoundDestService: false,
  bFoundWriteCharacteristics: false,
  bFoundNotifyCharacteristics: false,
  reconnectCounts : 0,
  connectCallback: null,
  valueChangeCallBack: null,
  timeoutCallBack: null,
  searchCallBack: null,
  timer : null,
  app : null,

  setApp : function(app) {
    this.app = app
  },

  initialize : function(deviceName, connectCallback, timeoutCallBack, searchCallBack) {
    let that = this;

    if (that.deviceId.length > 0 && searchCallBack == null) {
      connectCallback(1);
      return;
    }

    that.connectCallback = connectCallback;
    that.timeoutCallBack = timeoutCallBack;
    that.searchCallBack = searchCallBack;
    that.deviceName = deviceName;

    if (!wx.openBluetoothAdapter) {
      wx.showModal({
        title: '提示',
        showCancel: false,
        content:
          '当前微信版本过低，无法使用该功能，请升级到最新微信版本后重试。'
      })
      return;
    }

    wx.openBluetoothAdapter({
      success: res => {
        console.log('2. 初始化蓝牙模块')
        that.searchBluetooth()
      }, 
      fail(err) {
        console.log(err);
        if (err.errCode == 10001) {
          wx.showModal({
            title: '提示',
            showCancel: false,
            content:'蓝牙未开启，请在手机设置中开启'
          })
        }
        that.watchBluetoothStateChange();
      }
    })
  },

  isConncted : function() {
    if (this.deviceId.length > 0) {
      return true;
    } else {
      return false;
    }
  },

  watchBluetoothStateChange : function() {
    console.log("watchBluetoothStateChange");
    let that = this;

    wx.onBluetoothAdapterStateChange(res => {
      console.log('3. 获取蓝牙适配器状态改变', res.available, res.discovering)

      that.available = res.available,
      that.discovering = res.discovering
    
      if (!that.last_available && res.available) {
        that.searchBluetooth()
      } 

      that.last_available = res.available
    })
  },

  // 查找设备
  searchBluetooth : function() {
    wx.showLoading();

    let that = this;
    that.timer = setTimeout(() => {
      wx.hideLoading();
      if (that.timeoutCallBack) {
        that.timeoutCallBack();
      }
    }, 5000);

    console.log("searchBluetooth");
    wx.startBluetoothDevicesDiscovery({
      allowDuplicatesKey: true,
      success: res => {
        console.log('4. 开始查找设备')
        that.watchBluetoothFound()
      },
      fail: err => {
        console.log('4.1-err', err)
      }
    })
  },

  // 监听寻找到新设备
  watchBluetoothFound: function () {
    let that = this;

    wx.onBluetoothDeviceFound(res => {
      if (that.searchCallBack) {
        let devices = that.devices
        for (let dev of res.devices) {
          let found = underscore.find(devices, (item) => {
            return item && item.deviceId === dev.deviceId
          })
          if (found === undefined) {
            if (dev.localName) {
              console.log(dev.localName)
              wx.hideLoading();
              that.devices.push(dev)
              that.searchCallBack(that.devices)
            }
          }
        }
      } else {
        for (let device of res.devices) {
          if (device.localName && device.localName == that.deviceName && that.deviceId.length == 0) {
            console.log('5. 搜索成功, 目标设备为：', device.localName)
            // 连接成功 需要断开蓝牙搜索
            that.stopSearchBluetooth()
            that.connectBluetooth(device.deviceId, null)
          }
        }

        // let device = res.devices[0]
        // console.log('device', device.localName, device.name);
        // if (device.localName) {
        //   console.log('5. 搜索成功, 目标设备为：', device.localName)
        //   // 连接成功 需要断开蓝牙搜索
        //   that.stopSearchBluetooth()
        //   that.connectBluetooth(device.deviceId, null)
        // }
      }
    })
  },

  disconnect : function() {
    let that = this
    wx.closeBLEConnection({
      deviceId: that.deviceId,
      success (res) {
        console.log(res)
        that.deviceId = ""
      }
    })
  },

  clearBluetooth : function() {
    this.stopSearchBluetooth()
    this.devices = []
  },

  // 停止查找
  stopSearchBluetooth : function() {
    wx.stopBluetoothDevicesDiscovery({
      success: res => {
        console.log('6. 蓝牙停止查找')
      },
      fail: (err) => {
        console.log('6.1-err', err);
        // reject(err);
      },
    })
  },

  connectBluetooth : function(deviceId, connectCallback) {
    let that = this;
    that.deviceId = deviceId
    if (connectCallback) {
      that.connectCallback = connectCallback
    }

    that.reconnectCounts++
    wx.createBLEConnection({
      deviceId,
      success: res => {
        console.log('7. 建立设备连接')
        that.reconnectCounts = null
        that.getBluetoothServices()
      },
      fail: err => {
        console.log('7.1-err 连接失败，结束', err)
        console.log('重新连接蓝牙通讯第:', that.reconnectCounts, ' 次')
        if (that.reconnectCounts <= 3) {
          that.connectBluetooth(deviceId, connectCallback)
        } else {
          // reject({ deviceId })
          let tt = setTimeout(() => {
            clearTimeout(tt)
            tt = null
            showToastSimple('蓝牙异常')
          }, 200)
          that.closeFromAirtu({ deviceId })
        }
      }
    })

    wx.onBLEConnectionStateChange(function(res) {
      // 该方法回调中可以用于处理连接意外断开等异常情况
      if (!res.connected) {
        that.deviceId = '';
      }
    })

    wx.onBLECharacteristicValueChange(function (res) {
      console.log(`characteristic ${res.characteristicId} has changed, now is ${res.value}`)
      var result = util.ab2hex(res.value)
      const info = "ble reveive: length:" + result.length + " content:" + result
      // console.log(info)
      if (that.valueChangeCallBack) {
        that.valueChangeCallBack(result);
      }
    })
  },

  // 获取设备服务
  getBluetoothServices: function() {
    let that = this;
    let deviceId = that.deviceId;

    wx.getBLEDeviceServices({
      deviceId,
      success: res => {
        console.log('8. 获取设备服务')
        for (let service of res.services) {
          console.log("found service uuid---" + service.uuid);
          if (service.uuid === that.serviceId) {
            that.bFoundDestService = true;

            wx.getBLEDeviceCharacteristics({
              deviceId: deviceId,
              serviceId: service.uuid,
              success: (res) => {
                for (let chact of res.characteristics) {
                  console.log("found characteristics uuid---" + chact.uuid);

                  if (chact.uuid === that.writeCharacteristicId) {
                    that.bFoundWriteCharacteristics = true;
                  }

                  if (chact.uuid === that.notifyCharacteristicId) {
                    // 在某些android手机上一直返回fail，但是实际上能返回数据，不知道啥情况
                    wx.notifyBLECharacteristicValueChange({
                      state: true,
                      deviceId: deviceId,
                      serviceId: service.uuid,
                      characteristicId: chact.uuid,
                      complete: function (res) {
                        console.log('notifyBLECharacteristicValueChanged complete', res.errMsg)
                        that.bFoundNotifyCharacteristics = true;
                        that.checkDone()
                      }
                    })
                  }
                }
              },
              fail: err => {
                console.log('9.2-err', err)
              }
            })
          }
        }
      },
      fail: err => {
        console.log('8.1-err', err)
        // reject({ deviceId })
      }
    })
  },

  checkDone : function() {
    if (this.bFoundDestService && this.bFoundWriteCharacteristics) {
      wx.hideLoading();
      clearTimeout(this.timer);
      this.timer = null;
      this.connectCallback(0);
      wx.showToast({
        title: '连接成功',
        icon: 'none'
      })
    }
  },
  
  closeFromAirtu : function() {
    let that = this;
    let deviceId = that.deviceId;

    if (deviceId) {
      wx.closeBLEConnection({
        deviceId,
        success: () => {
          console.log('断开与低功耗蓝牙设备的连接')
          const info = "断开与低功耗蓝牙设备的连接"
          that.app.writeLog(info)
          wx.closeBluetoothAdapter({
            success: () => {
              console.log('关闭蓝牙模块')
              const info = "关闭蓝牙模块"
              that.app.writeLog(info)
              // 断开蓝牙的连接 （初始化所有的状态）
              that.deviceId = ''
              that.bFoundDestService = false
              that.bFoundWriteCharacteristics = false
              that.bFoundNotifyCharacteristics = false
            }
          })
          
        },
        fail: err => {
          console.log('断开与低功耗蓝牙设备的连接--err', err)
          const info = "断开与低功耗蓝牙设备的连接"
          that.app.writeLog(info)
          wx.closeBluetoothAdapter({
            success: () => {
              console.log('关闭蓝牙模块')
              const info = "关闭蓝牙模块"
              that.app.writeLog(info)
              // 断开蓝牙的连接 （初始化所有的状态）
              that.deviceId = ''
              that.bFoundDestService = false
              that.bFoundWriteCharacteristics = false
              that.bFoundNotifyCharacteristics = false
            }
          })
        }
      })
    } else {
      wx.closeBluetoothAdapter({
        success: () => {
          console.log('关闭蓝牙模块')
          const info = "关闭蓝牙模块"
          that.app.writeLog(info)
          // 断开蓝牙的连接 （初始化所有的状态）
          that.deviceId = ''
          that.bFoundDestService = false
          that.bFoundWriteCharacteristics = false
          that.bFoundNotifyCharacteristics = false
        }
      })
    }
  },

  readData : function() {
    let that = this;
    let deviceId = that.deviceId;
    let serviceId = that.serviceId;
    let writeCharacteristicId = that.writeCharacteristicId;

    wx.readBLECharacteristicValue({
      deviceId,
      serviceId,
      writeCharacteristicId,
      success (res) {
        console.log('readBLECharacteristicValue:', res.errCode)
      }
    })
  },

  sendCommand : function(packetData, callback) {
    let that = this;
    let deviceId = that.deviceId;
    let serviceId = that.serviceId;
    let writeCharacteristicId = that.writeCharacteristicId;

    let buffer = new ArrayBuffer(packetData.length)
    let dataView = new DataView(buffer)
    for (var i = 0; i < packetData.length; i++) {
      dataView.setUint8(i, packetData[i])
    }

    console.log("packet data --- " + packetData)

    wx.writeBLECharacteristicValue({
      deviceId: deviceId,
      serviceId: serviceId,
      characteristicId: writeCharacteristicId,
      value: buffer,
      success: (res) => {
        // console.log(`data sent. [${res.errMsg}]`)
        callback()
      },
      fail:(res) => {
        console.log(`data sent failed. [${res.errMsg}]`)
        callback()
      }
    })
  },

  crc16 : function(buffer) {
    const polynomial = 0xA001;  // 多项式，低位优先的0x8005反射版
    let crc = 0xFFFF;           // 初始值

    for (let byte of buffer) {
        crc ^= byte; // 将字节与 CRC 的低字节进行异或

        for (let i = 0; i < 8; i++) {
            if (crc & 0x0001) {
                crc = (crc >> 1) ^ polynomial;  // 如果最低位为1，右移后与多项式异或
            } else {
                crc = crc >> 1;  // 否则直接右移
            }
        }
    }

    crc = crc & 0xFFFF;  // 取低16位作为最终CRC值
    const lowByte = crc & 0xFF;          // 低8位
    const highByte = (crc >> 8) & 0xFF;  // 高8位


    // 返回补0后的4字符长度的字符串，转为16进制并大写
    return [lowByte, highByte]
  },

  getCommandCrc16: function(command) {
    // const data = Buffer.from(command);

    // 计算 CRC-16
    const crc = this.crc16(command);
    const result = command.concat(crc)

    return result
  },

  parseSNResponse : function(res, format2AscII) {
    let hexString = res.substring(6, res.length-4)
    if (format2AscII) {
      return util.hexToAscii2(hexString)
    } else {
      return hexString
    }
  },

  getSN : async function() {
    let totalCount = 74
    let data = this.getCommandCrc16([0x0F, 0x03, 0x10, 0x00, 0x00, 0x10])
    return await this.send_command_wait_done(data, totalCount)
  }, 

  getPack : async function() {
    let totalCount = 74
    let data = this.getCommandCrc16([0x0F, 0x03, 0x10, 0x10, 0x00, 0x10])
    return await this.send_command_wait_done(data, totalCount)
  }, 

  getDesingerCap : async function(repeate) {
    if (this.busy && repeate) {
      return
    }

    this.busy = true
    let totalCount = 22
    let data = this.getCommandCrc16([0x0F, 0x03, 0x11, 0x01, 0x00, 0x03])
    let res = await this.send_command_wait_done(data, totalCount)
    let design = (this.parse2int(res.substr(0, 4), 16) * 0.1).toFixed(1)
    let bnums = this.parse2int(res.substr(4, 4), 16)
    let resnse = this.parse2int(res.substr(8, 4), 16)

    totalCount = 14
    data = this.getCommandCrc16([0x0F, 0x03, 0x11, 0x12, 0x00, 0x01])
    res = await this.send_command_wait_done(data, totalCount)
    let limit = this.parse2int(res.substr(0, 4), 16)

    this.busy = false
    this.last_cap = [design, bnums, resnse, limit]
    return [design, bnums, resnse, limit]
  }, 

  getOVPROT : async function() {
    let totalCount = 14
    let data = this.getCommandCrc16([0x0F, 0x03, 0x11, 0x0E, 0x00, 0x01])
    let res = await this.send_command_wait_done(data, totalCount)
    return this.parse2int(res, 16)
  }, 

  getFull : async function() {
    let totalCount = 66
    let data = this.getCommandCrc16([0x0F, 0x03, 0x10, 0x20, 0x00, 0x0E])
    let res = await this.send_command_wait_done(data, totalCount)

    let total = (this.parse2int(res.substr(0, 4), 16) * 0.01).toFixed(2)
    let electri_h = this.parse2int(res.substr(4, 4), 16)
    let electri_l = this.parse2int(res.substr(8, 4), 16)
    let electri_orign = ((electri_h << 16) | electri_l)
    let electri = (electri_orign * 0.001).toFixed(2);
    let power = (total * electri).toFixed(3)
    let precent = (this.parse2int(res.substr(12, 4), 16) * 0.01).toFixed(2)
    let shouming = (this.parse2int(res.substr(16, 4), 16) * 0.01).toFixed(2)
    let progress = precent / 2
    let full = (this.parse2int(res.substr(20, 4), 16) * 0.1).toFixed(1)
    let remain = (full * precent * 0.01).toFixed(2);
    let loop_counter = this.parse2int(res.substr(24, 4), 16)
    let chongdian_counter = this.parse2int(res.substr(28, 4), 16)
    let chongdian_total_h = this.parse2int(res.substr(32, 4), 16)
    let chongdian_total_l = this.parse2int(res.substr(36, 4), 16)
    let chongdian_total = ((chongdian_total_h << 16) | chongdian_total_l)
    chongdian_total = (chongdian_total * 0.1).toFixed(1);
    let fangdian_total_h = this.parse2int(res.substr(40, 4), 16)
    let fangdian_total_l = this.parse2int(res.substr(44, 4), 16)
    let fangdian_total = ((fangdian_total_h << 16) | fangdian_total_l)
    fangdian_total = (fangdian_total * 0.1).toFixed(1);
    let junheng_total_h = this.parse2int(res.substr(48, 4), 16)
    let junheng_total_l = this.parse2int(res.substr(52, 4), 16)
    let junheng_total = ((junheng_total_h << 16) | junheng_total_l)

    return [precent + "%", full, remain, progress, total, electri, power, loop_counter, electri_orign, chongdian_counter, chongdian_total, shouming, fangdian_total, junheng_total]
  }, 

  getBSystemInfo : async function() {
    let totalCount = 14
    let data = this.getCommandCrc16([0x0F, 0x03, 0x10, 0x31, 0x00, 0x01])
    let res = await this.send_command_wait_done(data, totalCount)
    let binary = util.hexToBinaryString(res)
    let chongdian_mos = binary.substr(-1, 1) == "1" ? true : false; 
    let fangdian_mos = binary.substr(-2, 1) == "1" ? true : false;
    let chongdian_state = binary.substr(-5, 1) == "1" ? true : false;
    let fangdian_state = binary.substr(-6, 1) == "1" ? true : false;

    return [chongdian_mos, fangdian_mos, chongdian_state, fangdian_state]
  }, 

  getEveryVoltage : async function() {
    let totalCount = 142
    let data = this.getCommandCrc16([0x0F, 0x03, 0x10, 0x3B, 0x00, 0x21])
    let res = await this.send_command_wait_done(data, totalCount)
    let count = this.parse2int(res.substr(0, 4), 16)
    let voltages = []

    for (let i = 1; i <= count; i++) {
      var v = this.parse2int(res.substr(4 * i, 4), 16)
      voltages.push(v)
    }

    return voltages
  }, 

  getTemperature : async function() {
    let totalCount = 42
    let data = this.getCommandCrc16([0x0F, 0x03, 0x10, 0x33, 0x00, 0x08])
    let res = await this.send_command_wait_done(data, totalCount)
    let mos_t = this.parse2int(res.substr(0, 4), 16)
    let t1 = this.parse2int(res.substr(4, 4), 16)
    let t2 = this.parse2int(res.substr(8, 4), 16)
    let t3 = this.parse2int(res.substr(12, 4), 16)
    let t4 = this.parse2int(res.substr(16, 4), 16)
    let t5 = this.parse2int(res.substr(20, 4), 16)
    let huanjing_t = this.parse2int(res.substr(24, 4), 16)

    let list = [mos_t, huanjing_t, t1, t2, t3, t4, t5]
    for (let i = 0; i < list.length; i++) {
      list[i] = (list[i] * 0.1).toFixed(1)
    }
    return list
  },

  getProtectInfo : async function() {
    let totalCount = 22
    let data = this.getCommandCrc16([0x0F, 0x03, 0x10, 0x2E, 0x00, 0x03])
    let res = await this.send_command_wait_done(data, totalCount)
    let p1 = res.substr(0, 4)
    let p2 = res.substr(4, 4)
    let p3 = res.substr(8, 4)
    let p1_binary = util.hexToBinaryString(p1)
    let p2_binary = util.hexToBinaryString(p2)
    let p3_binary = util.hexToBinaryString(p3)
    let p1_info = ["LV1-放电低温保护","LV1-充电低温保护","LV1-放电高温保护","LV1-充电高温保护","LV1-环境高温保护","LV1-MOS高温保护","LV1-温差保护","LV1-放电过流2保护","LV1-放电过流1保护","LV1-充电过流保护","LV1-压差保护","LV1-深度过放保护","LV1-过放欠压保护","LV1-过充过压保护","LV1-总压过放欠压保护","LV1-总压过充过压保护"]
    let p2_info = ["LV2-放电低温保护","LV2-充电低温保护","LV2-放电高温保护","LV2-充电高温保护","LV2-环境高温保护","LV2-MOS高温保护","LV2-短路保护","LV2-放电过流2保护","LV2-放电过流1保护","LV2-充电过流保护","LV2-压差保护","LV2-深度过放保护","LV2-过放欠压保护","LV2-过充过压保护","LV2-总压过放欠压保护","LV2-总压过充过压保护"]
    let warning_info_list = ["","","","采集线断线损坏","非法拆除故障","振动故障","进水故障","电量低","外部存储损坏","恒流损坏","加热损坏","均衡损坏","MCU异常","AFE异常","放电MOS损坏","充电MOS损坏"]

    let protect_info = ""
    let warning_list = []

    for (let i = 0; i < p1_binary.length; i++) {
      if (p1_binary.substr(i, 1) == "1") {
        protect_info = protect_info + p1_info[i] + ";"
      }
    }

    for (let i = 0; i < p2_binary.length; i++) {
      if (p2_binary.substr(i, 1) == "1") {
        protect_info = protect_info + p2_info[i] + ";"
      }
    }

    let mos_bad = false
    for (let i = 0; i < p3_binary.length; i++) {
      if (p3_binary.substr(i, 1) == "1") {
        warning_list.push(warning_info_list[i])
        if (warning_info_list[i].indexOf("MOS损坏") > -1) {
          mos_bad = true
        }
      }
    }

    return [protect_info, warning_list, mos_bad]
  },

  getParamsWrapper : async function(flag){
    if (this.busy) {
      await util.sleep(500)

      if (this.busy) {
        await util.sleep(500)
      }
    }

    if (flag) {
      const params = await this.getParams()
      const second_params = await this.getAFEParams()

      return {params, second_params}
    } else {
      const params = await this.getFastParams()
      return {params}
    }
  },

  getTemptureProtectParams : async function() {
    this.busy = true
    let totalCount = 66
    let data = this.getCommandCrc16([0x0F, 0x03, 0x11, 0x29, 0x00, 0x0E])
    let res = await this.send_command_wait_done(data, totalCount)
    var result = []
    var offset = -4
    var num = 4
    var enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    var throld = this.parse2int(res.substr(offset+=4, num), 16)
    var delay = this.parse2int(res.substr(offset+=4, num), 16)
    var shifang = this.parse2int(res.substr(offset+=4, num), 16)
    
    result.push(throld)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    result.push(throld)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    result.push(throld)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    result.push(throld)

    this.busy = false
    return result
  },

  getParams : async function() {
    this.busy = true
    let totalCount = 298
    let data = this.getCommandCrc16([0x0F, 0x03, 0x11, 0x05, 0x00, 0x48])
    let res = await this.send_command_wait_done(data, totalCount)
    var address = 4357
    var result = []
    var offset = -4
    var num = 4
    var enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    var throld = (this.parse2int(res.substr(offset+=4, num), 16) * 0.01).toFixed(2)
    var delay = this.parse2int(res.substr(offset+=4, num), 16) * 10
    var shifang = (this.parse2int(res.substr(offset+=4, num), 16) * 0.01).toFixed(2)
    var obj = { name: "总压过充保护", enable: enable, address: address++, name1: "过充阈值_V", value1: throld, address1: address++, name2: "延迟判定_ms", value2: delay, address2: address++, name3: "释放阈值_V", value3: shifang, address3: address++, };
    obj.ratio1 = 100
    obj.ratio2 = 0.1
    obj.ratio3 = 100
    obj.type = "volatge"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = (this.parse2int(res.substr(offset+=4, num), 16) * 0.01).toFixed(2)
    delay = this.parse2int(res.substr(offset+=4, num), 16) * 10
    shifang = (this.parse2int(res.substr(offset+=4, num), 16) * 0.01).toFixed(2)
    obj = {name : "总压过放保护",enable : enable, address: address++,name1 : "过放阈值_V",value1 : throld, address1: address++,name2 : "延迟判定_ms",value2 : delay, address2: address++,name3 : "释放阈值_V",value3 : shifang, address3: address++,};
    obj.ratio1 = 100
    obj.ratio2 = 0.1
    obj.ratio3 = 100
    obj.type = "volatge"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16) * 10
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = {name : "过充电压保护",enable : enable, address: address++,name1 : "过充阈值_mV",value1 : throld, address1: address++,name2 : "延迟判定_ms",value2 : delay, address2: address++,name3 : "释放阈值_mV",value3 : shifang, address3: address++,};
    obj.ratio1 = 1
    obj.ratio2 = 0.1
    obj.ratio3 = 1
    obj.type = "volatge"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16) * 10
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = {name : "过放电压保护",enable : enable, address: address++,name1 : "过放阈值_mV",value1 : throld, address1: address++,name2 : "延迟判定_ms",value2 : delay, address2: address++,name3 : "释放阈值_mV",value3 : shifang, address3: address++,};
    obj.ratio1 = 1
    obj.ratio2 = 0.1
    obj.ratio3 = 1
    obj.type = "volatge"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16) * 10
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = {name : "深度放电保护",enable : enable, address: address++,name1 : "阈值_mV",value1 : throld, address1: address++,name2 : "延迟判定_ms",value2 : delay, address2: address++,name3 : "释放阈值_mV",value3 : shifang, address3: address++,};
    obj.ratio1 = 1
    obj.ratio2 = 0.1
    obj.ratio3 = 1
    obj.type = "volatge"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16) * 10
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = {name : "压差保护",enable : enable, address: address++,name1 : "阈值_mV",value1 : throld, address1: address++,name2 : "延迟判定_ms",value2 : delay, address2: address++,name3 : "释放阈值_mV",value3 : shifang, address3: address++,};
    obj.ratio1 = 1
    obj.ratio2 = 0.1
    obj.ratio3 = 1
    obj.type = "volatge"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = (this.parse2int(res.substr(offset+=4, num), 16) * 0.1).toFixed(1)
    delay = this.parse2int(res.substr(offset+=4, num), 16) * 10
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = {name : "充电过流",enable : enable, address: address++,name1 : "阈值_A",value1 : throld, address1: address++,name2 : "延迟判定_ms",value2 : delay, address2: address++,name3 : "释放阈值_S",value3 : shifang, address3: address++,};
    obj.ratio1 = 10
    obj.ratio2 = 0.1
    obj.ratio3 = 1
    obj.type = "electric"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = (this.parse2int(res.substr(offset+=4, num), 16) * 0.1).toFixed(1)
    delay = this.parse2int(res.substr(offset+=4, num), 16) * 10
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = {name : "放电过流1",enable : enable, address: address++,name1 : "阈值_A",value1 : throld, address1: address++,name2 : "延迟判定_ms",value2 : delay, address2: address++,name3 : "释放阈值_S",value3 : shifang, address3: address++,};
    obj.ratio1 = 10
    obj.ratio2 = 0.1
    obj.ratio3 = 1
    obj.type = "electric"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = (this.parse2int(res.substr(offset+=4, num), 16) * 0.1).toFixed(1)
    delay = this.parse2int(res.substr(offset+=4, num), 16) * 10
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = {name : "放电过流2",enable : enable, address: address++,name1 : "阈值_A",value1 : throld, address1: address++,name2 : "延迟判定_ms",value2 : delay, address2: address++,name3 : "释放阈值_S",value3 : shifang, address3: address++,};
    obj.ratio1 = 10
    obj.ratio2 = 0.1
    obj.ratio3 = 1
    obj.type = "electric"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = {name : "功率过温保护",enable : enable, address: address++,name1 : "阈值_℃",value1 : throld, address1: address++,name2 : "延迟判定_S",value2 : delay, address2: address++,name3 : "释放阈值_℃",value3 : shifang, address3: address++,};
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "temp"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = {name : "环境过温保护",enable : enable, address: address++,name1 : "阈值_℃",value1 : throld, address1: address++,name2 : "延迟判定_S",value2 : delay, address2: address++,name3 : "释放阈值_℃",value3 : shifang, address3: address++,};
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "temp"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = {name : "充电过温保护",enable : enable, address: address++,name1 : "阈值_℃",value1 : throld, address1: address++,name2 : "延迟判定_S",value2 : delay, address2: address++,name3 : "释放阈值_℃",value3 : shifang, address3: address++,};
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "temp"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = {name : "放电过温保护",enable : enable, address: address++,name1 : "阈值_℃",value1 : throld, address1: address++,name2 : "延迟判定_S",value2 : delay, address2: address++,name3 : "释放阈值_℃",value3 : shifang, address3: address++,};
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "temp"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = {name : "充电低温保护",enable : enable, address: address++,name1 : "阈值_℃",value1 : throld, address1: address++,name2 : "延迟判定_S",value2 : delay, address2: address++,name3 : "释放阈值_℃",value3 : shifang, address3: address++,};
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "temp"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = {name : "放电低温保护",enable : enable, address: address++,name1 : "阈值_℃",value1 : throld, address1: address++,name2 : "延迟判定_S",value2 : delay, address2: address++,name3 : "释放阈值_℃",value3 : shifang, address3: address++,};
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "temp"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = {name : "温差保护",enable : enable, address: address++,name1 : "阈值_℃",value1 : throld, address1: address++,name2 : "延迟判定_S",value2 : delay, address2: address++,name3 : "释放阈值_℃",value3 : shifang, address3: address++,};
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "temp"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = {name : "加热设置",enable : enable, address: address++,name1 : "允许充电_℃",value1 : throld, address1: address++,name2 : "开始温度_℃",value2 : delay, address2: address++,name3 : "结束温度_℃",value3 : shifang, address3: address++,};
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "junheng"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = {name : "SOC低电量告警",enable : enable, address: address++,name1 : "系统告警_%",value1 : throld, address1: address++,name2 : "LV3告警_%",value2 : delay, address2: address++,name3 : "告警解除_%",value3 : shifang, address3: address++,};
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    result.push(obj)

    this.busy = false
    return result
  },

  getAFEParams2 : async function() {
    this.busy = true
    let totalCount = 26
    let data = this.getCommandCrc16([0x0F, 0x03, 0x08, 0x02, 0x00, 0x04])
    let res = await this.send_command_wait_done(data, totalCount)
    var result = []
    var offset = -4
    var num = 4
    var enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    var throld = this.parse2int(res.substr(offset+=4, num), 16)
    var delay = this.parse2int(res.substr(offset+=4, num), 16)
    var shifang = this.parse2int(res.substr(offset+=4, num), 16)

    this.busy = false
    return throld
  },

  getAFEParams : async function() {
    this.busy = true
    let totalCount = 162
    let data = this.getCommandCrc16([0x0F, 0x03, 0x08, 0x02, 0x00, 0x26])
    let res = await this.send_command_wait_done(data, totalCount)

    var address = 2050
    var result = []
    var offset = -4
    var num = 4
    var enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    var throld = this.parse2int(res.substr(offset+=4, num), 16)
    var delay = this.parse2int(res.substr(offset+=4, num), 16)
    var shifang = this.parse2int(res.substr(offset+=4, num), 16)
    var obj = { name: "二级过充保护", enable: enable, address: address++, name1: "过充阈值_mV", value1: throld, address1: address++, name2: "延迟判定_ms", value2: delay, address2: address++, name3: "释放阈值_mV", value3: shifang, address3: address++, };
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "volatge"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = { name: "二级过放保护", enable: enable, address: address++, name1: "过放阈值_mV", value1: throld, address1: address++, name2: "延迟判定_ms", value2: delay, address2: address++, name3: "释放阈值_mV", value3: shifang, address3: address++, };
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "volatge"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)

    obj = { name: "二级充电过流保护", enable: enable, address: address++, name1: "阈值_A", value1: throld, address1: address++, name2: "延迟判定_ms", value2: delay, address2: address++, name3: "释放模式", value3: shifang, address3: address++, };
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "electric"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    
    obj = { name: "二级放电过流1保护", enable: enable, address: address++, name1: "阈值_A", value1: throld, address1: address++, name2: "延迟判定_ms", value2: delay, address2: address++};
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "electric"
    result.push(obj)

    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    obj = { name: "二级放电过流2保护", enable: enable, address: -1, name1: "阈值_A", value1: throld, address1: address++, name2: "延迟判定_ms", value2: delay, address2: address++ };
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "electric"
    result.push(obj)

    throld = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = { name: "短路保护", enable: enable, address: -1, name1: "阈值_A", value1: throld, address1: address++, name2: "延迟判定_ms", value2: delay, address2: address++ , name3: "放电过流和短路释放模式", value3: shifang, address3: address++, };
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "electric"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = { name: "二级充电高温保护", enable: enable, address: address++ , name1: "阈值_℃", value1: throld, address1: address++, name2: "延迟判定_ms", value2: "", address2: -1 , name3: "释放_℃", value3: shifang, address3: address++, };
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "temp"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)

    obj = { name: "二级放电高温保护", enable: enable, address: address++ , name1: "阈值_℃", value1: throld, address1: address++, name2: "释放_℃", value2: shifang, address2: address++, name3: "充放电高温延时_ms", value3: delay, address2: address++ };
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "temp"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    obj = { name: "二级充电低温保护", enable: enable, address: address++ , name1: "阈值_℃", value1: throld, address1: address++, name2: "延迟判定_ms", value2: "", address2: -1 , name3: "释放_℃", value3: shifang, address3: address++, };
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "temp"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)

    obj = { name: "二级放电低温保护", enable: enable, address: address++ , name1: "阈值_℃", value1: throld, address1: address++, name2: "释放_℃", value2: shifang, address2: address++, name3: "充放电低温延时_ms", value3: delay, address3: address++ };
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "temp"
    result.push(obj)

    enable = this.parse2int(res.substr(offset+=4, num), 16) == 1 ? true : false
    throld = this.parse2int(res.substr(offset+=4, num), 16)
    shifang = this.parse2int(res.substr(offset+=4, num), 16)
    delay = this.parse2int(res.substr(offset+=4, num), 16)
    
    obj = { name: "自动均衡使能", enable: enable, address: address++ , name1: "均衡启动电压_mV", value1: throld, address1: address++, name2: "均衡启动模式(0:充电 1:充电和静置)", value2: shifang, address2: address++, name3: "均衡启动压差_mV", value3: delay, address3: address++ };
    obj.ratio1 = 1
    obj.ratio2 = 1
    obj.ratio3 = 1
    obj.type = "junheng"
    result.push(obj)

    this.busy = false
    return result
  },

  getFastParams : async function() {
    this.busy = true
    let result = []

    let totalCount = 34
    let data = this.getCommandCrc16([0x0F, 0x03, 0x08, 0x28, 0x00, 0x06])
    let res = await this.send_command_wait_done(data, totalCount)

    let enable = this.parse2int(res.substr(0, 4), 16)
    let qidong_voltage = this.parse2int(res.substr(4, 4), 16)
    let baohu_electri = this.parse2int(res.substr(16, 4), 16)
    let jingzhi_electri = this.parse2int(res.substr(20, 4), 16)
    
    totalCount = 26
    data = this.getCommandCrc16([0x0F, 0x03, 0x11, 0x49, 0x00, 0x04])
    res = await this.send_command_wait_done(data, totalCount)
    let soc_enable = this.parse2int(res.substr(0, 4), 16)
    let soc_sys = this.parse2int(res.substr(4, 4), 16)
    let soc_lv3 = this.parse2int(res.substr(8, 4), 16)
    let soc_clear = this.parse2int(res.substr(12, 4), 16)

    result = [
      ["预充预防使能", enable, "", false, 2088, 1],
      ["预充启动电压_mV", qidong_voltage, "", false, 2089, 1],
      ["充电管保护电流_mA", baohu_electri, "", false, 2092, 1],
      ["静止电流阈值_mA", jingzhi_electri, "", false, 2093, 1],
      ["SOC 低电量告警使能", soc_enable, "", false, 4425, 1],
      ["SOC 系统告警_%", soc_sys, "", false, 4426, 1],
      ["SOC LV3告警_%", soc_lv3, "", false, 4427, 1],
      ["SOC 解除告警_%", soc_clear, "", false, 4428, 1],
    ]
    this.busy = false
    return result
  },

  getBMSInfo : async function() {
    let totalCount = 18
    let data = this.getCommandCrc16([0x0F, 0x03, 0x18, 0x06, 0x00, 0x02])
    let res = await this.send_command_wait_done(data, totalCount)
    let chongdian = this.parse2int(res.substr(0, 4), 16)
    let fangdian = this.parse2int(res.substr(4, 4), 16)

    return [chongdian, fangdian]
  },

  parse2int : function(s, radix) {
    let result = parseInt(s, radix)
    if (result > 60000) {
      result = result - 65536
    }
    
    return result
  },

  writeValueWrapper : async function(address, value) {
    if (this.busy) {
      await util.sleep(500)
  
      if (this.busy) {
        await util.sleep(500)
      }
    }

    await this.writeValue(address, value)
  },

  
  writeValue : async function(address, value) {
    this.busy = true

    let totalCount = 16
    let address_bytes = util.decimalToFixedByteArray(address, 2)
    let date_len_bytes = util.decimalToFixedByteArray(1, 2)
    if (parseInt(value) < 0) {
      value = 65536 + value
    }
    let value_bytes = util.decimalToFixedByteArray(value, 2)
    let prefixs = [0x0F, 0x10]
    let command = prefixs.concat(address_bytes, date_len_bytes, [0x02], value_bytes)
    let data = this.getCommandCrc16(command)
    await this.send_command_wait_done(data, totalCount)
    this.busy = false
  },

  send_command_wait_done: function(command, totalCount) {
    const that = this
    return new Promise(function (resolve, reject) {
      that.sendCommand(command, ()=>{});
      var recvBuffer = ""
      // var totalCount = 74
      that.valueChangeCallBack = (res) => {
        recvBuffer += res
        if (recvBuffer.length == totalCount) {
          // console.log("收到完整的包:", recvBuffer, totalCount)
          let format = totalCount == 74 ? true : false;
          const result = that.parseSNResponse(recvBuffer, format)
          resolve(result)
        }
      }
    })
  }
}

module.exports = bluetooth